﻿module stuff

open System
open System.IO
open GenericCurrying
open CSharpRef
open EmailValidationTests
open FsUnit

//[<EntryPoint>]
let test p = 
    //let f = FP.curry String.Compare // does not compile
    let f = FP.curry2 String.Compare
    //let c = String.Compare.Curried // does not compile
    let someMethod = FP.curry Class1.SomeMethod // does not compile when overloaded
    let c = Class1()
    let anotherMethod = FP.curry c.NonStaticMethod    
    printf "%A\n" (anotherMethod "" "")
    printf "%A\n" (anotherMethod "" "")

    let c = Class1()
    let anotherMethod = FP.curry c.NonStaticMethod    
    printf "%A\n" (anotherMethod "" "")
    
    let _ = Console.ReadKey()
    0

let rec fix f x = f (fix f) x

let GetFilesNR f d = 
    Seq.append (Directory.GetFiles d) (Seq.collect f (Directory.GetDirectories d))
    
let printWrapper f fp p =
    let result = f fp p
    printf "%A\n" result
    result
    
let GetFilesNRWrapper = fix (printWrapper (fun f d -> Seq.append (Directory.GetFiles d) (Seq.collect f (Directory.GetDirectories d))))

    
let dgetfiles d = 
    //Directory.GetFiles d
    ["a"; "b"]
    
let dgetdirs d = 
    //Directory.GetDirectories d
    ["d1"; "d2"]
        
let rec GetFiles d = 
    //Seq.append (Directory.GetFiles d) (Seq.collect GetFiles (Directory.GetDirectories d))
    
    seq {
        yield! Directory.GetFiles d
        yield! Seq.collect GetFiles (Directory.GetDirectories d)
    }
    
let rec GetFilesF d f = 
    let rec GetFilesD dirs f = 
        match dirs with
        | [] -> ()
        | h::t -> 
            Directory.GetFiles h |> Seq.iter f
            GetFilesD (Seq.toList (Seq.append (Directory.GetDirectories h) t)) f
    GetFilesD (d::[]) f

   
let rec LGetFilesF d f =
    let rec GetFilesD dirs f = 
        match dirs with
        | LazyList.Nil -> ()
        | LazyList.Cons(h,t) ->
            printf "%A\n" h
            Directory.GetFiles h |> Seq.iter f
            GetFilesD (LazyList.ofSeq (Seq.append (Directory.GetDirectories h) t)) f
            
    GetFilesD (LazyList.ofList (d::[])) f

/// From http://stackoverflow.com/questions/1902749/a-timeit-function-for-f/1902858#1902858
let timeit f v = 
    printfn "Start %A" f
    let watch = System.Diagnostics.Stopwatch.StartNew()
    let res = f v 
    watch.Stop()
    printfn "Needed %A" watch.Elapsed
    res
    
let runGroupConsecutiveTests () =

    specs "eager" [
        spec "1 group"
            (GroupConsecutiveIntegers.groupConsec [1;2;3] |> should equal [[1;2;3]])
        spec "2 groups"
            (GroupConsecutiveIntegers.groupConsec [1;2;4;5] |> should equal [[1;2];[4;5]])
        (*spec "perf"
            (timeit GroupConsecutiveIntegers.groupConsec hugeList |> ignore; pass) *)
    ]

    specs "lazy" [
        spec "1 group"
            (GroupConsecutiveIntegers.lazyGroupConsec2 [1;2;3] |> should equal (Seq.ofList [[1;2;3]]))
        spec "2 groups"
            (GroupConsecutiveIntegers.lazyGroupConsec2 [1;2;4;5] |> should equal (Seq.ofList [[1;2]; [4;5]]))
        spec "2 groups"
            (GroupConsecutiveIntegers.lazyGroupConsec2 [1;2;4] |> should equal (Seq.ofList [[1;2]; [4]]))
        (* spec "perf"
            (timeit Seq.toList (GroupConsecutiveIntegers.lazyGroupConsec2 range) |> ignore; pass) *)
    ]
    printfn "%s" (Results.summary())

    let range = {1..1000}
    timeit GroupConsecutiveIntegers.groupConsec (List.ofSeq range) |> ignore
    timeit GroupConsecutiveIntegers.lazyGroupConsec (LazyList.ofSeq range) |> ignore
    timeit GroupConsecutiveIntegers.lazyGroupConsec2 range |> ignore
    timeit GroupConsecutiveIntegers.lazyGroupConsec3 range |> ignore
    //timeit Seq.toList range |> ignore
    
    ()
